package com.heima.comment.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.aliyun.GreenTextScan;
import com.heima.comment.service.CommentHotService;
import com.heima.comment.service.CommentService;
import com.heima.comment.utils.ScanText;
import com.heima.common.constants.article.HotArticleConstants;
import com.heima.common.excpetion.CustException;
import com.heima.feign.user.UserFeign;
import com.heima.model.comment.dtos.CommentDTO;
import com.heima.model.comment.dtos.CommentLikeDTO;
import com.heima.model.comment.dtos.CommentSaveDTO;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.comment.vos.ApCommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.mess.app.UpdateArticleMess;
import com.heima.model.threadlocal.AppThreadLocalUtils;
import com.heima.model.user.pojos.ApUser;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

@Service("CommentService")
@Slf4j
public class CommentServiceImpl implements CommentService {
    //云服务文本自动审核
    @Autowired
    GreenTextScan textScan;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    RabbitTemplate rabbitTemplate;

    @Autowired
    UserFeign userFeign;

    @Autowired
    MongoTemplate mongoTemplate;

    @Autowired
    ScanText scanText;

    @Autowired
    CommentHotService commentHotService;

    @Autowired
    RedissonClient redisson;

    /**
     * 保存评论
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult saveComment(CommentSaveDTO dto) {
        // 参数校验
        {
            String content = dto.getContent();

            // TODO 使用分组校验

            content = scanText.scan(content);

            ApUser user = AppThreadLocalUtils.getUser();

            ResponseResult<ApUser> result = userFeign.findUserById(user.getId());

            if (result.getCode() != 0 || content == null)
                CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR);

            ApComment comment = new ApComment();
            ApUser apUser = result.getData();

            comment.setContent(content);
            comment.setAuthorId(apUser.getId());
            comment.setArticleId(dto.getArticleId());
            comment.setAuthorName(apUser.getName());
            comment.setImage(apUser.getImage());
            comment.setCreatedTime(new Date());
            comment.setFlag((short) 0);
            comment.setLikes(0);
            comment.setReply(0);
            // TODO 添加频道信息


            mongoTemplate.save(comment);
            // 根据用户执行的操作向MQ发送评论情况消息
            {
                UpdateArticleMess articleMess = new UpdateArticleMess();
                articleMess.setType(UpdateArticleMess.UpdateArticleType.COMMENT);
                articleMess.setAdd(2);
                articleMess.setArticleId(dto.getArticleId());
                //发送消息
                rabbitTemplate.convertAndSend(HotArticleConstants.HOT_ARTICLE_SCORE_BEHAVIOR_QUEUE, JSON.toJSONString(articleMess));
            }
        }
        return ResponseResult.okResult();
    }

    /**
     * 点赞评论
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult like(CommentLikeDTO dto) {
        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null)
            CustException.cust(AppHttpCodeEnum.NEED_LOGIN);

        RLock rLock = redisson.getLock("Likes-lock");
        rLock.lock();

        ApComment apComment;
        //执行点赞
        try {
            apComment = mongoTemplate.findOne(Query.query(Criteria.where("id").is(dto.getCommentId())), ApComment.class);

            if (apComment == null)
                CustException.cust(AppHttpCodeEnum.PARAM_INVALID);

            Short operation = dto.getOperation();
            // 0点赞 1取消点赞
            if (operation == 1) {
                //取消点赞 -> 赞数减一
                Integer likes = apComment.getLikes();
                //删除点赞信息
                mongoTemplate.remove(Query.query(Criteria.where("commentId").is(apComment.getId())
                        .and("authorId").is(user.getId())
                ), ApCommentLike.class);

                if (likes == 0)
                    CustException.cust(AppHttpCodeEnum.PARAM_INVALID);
                apComment.setLikes(likes - 1);
                mongoTemplate.save(apComment);

            } else {
                // 点赞 -> 未点过赞 ->保存信息
                ApCommentLike commentLike = mongoTemplate.findOne(Query.query(Criteria.where("commentId").is(apComment.getId())
                        .and("authorId").is(user.getId())), ApCommentLike.class);
                if (commentLike != null) {
                    CustException.cust(AppHttpCodeEnum.PARAM_INVALID, "请勿重复点赞");
                }

                apComment.setLikes(apComment.getLikes() + 1);
                if (apComment.getLikes() >= 10) {
                    // 计算评论是否能成为热点评论
                    commentHotService.hotCommentExecutor(apComment);
                }
                mongoTemplate.save(apComment);
                //保存点赞数据
                ApCommentLike apCommentLike = new ApCommentLike();
                apCommentLike.setCommentId(apComment.getId());
                apCommentLike.setAuthorId(apComment.getAuthorId());
                apCommentLike.setOperation((short) 0);
                mongoTemplate.save(apCommentLike);
            }
        } finally {
            //解锁
            rLock.unlock();
        }

        HashMap<String, Object> hashMap = new HashMap<>(1);
        hashMap.put("likes", apComment.getLikes());
        return ResponseResult.okResult(hashMap);
    }

    /**
     * 根据文章id查询评论列表
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult load(CommentDTO dto) {
        Integer pageSize = dto.getSize();
        if (pageSize == null || pageSize < 10)
            pageSize = 10;

        // 获取评论列表
        List<ApComment> commentList;

        //是首页
        if (dto.getIndex() == 1) {
            //是首页 先查询热评
            commentList = mongoTemplate.find(Query.query(Criteria
                            .where("articleId").is(dto.getArticleId())
                            .and("createdTime").lt(dto.getMinDate()).and("flag").is(1))
                    .limit(pageSize).with(Sort.by(Sort.Direction.DESC, "likes")), ApComment.class);
            //减去长度
            pageSize = pageSize - commentList.size();

            //查询普通评论
            commentList.addAll(mongoTemplate.find(Query.query(Criteria
                            .where("articleId").is(dto.getArticleId())
                            .and("createdTime").lt(dto.getMinDate()).and("flag").is(0))
                    .with(Sort.by(Sort.Direction.DESC, "createdTime"))
                    .limit(pageSize), ApComment.class));


        } else {
            //获取评论列表
            commentList = mongoTemplate.find(Query.query(Criteria
                            .where("articleId").is(dto.getArticleId())
                            .and("createdTime").lt(dto.getMinDate()))
                    .limit(pageSize), ApComment.class);
        }


        //判断当前用户是否登录
        ApUser user = AppThreadLocalUtils.getUser();
        //未登录或者没有评论直接返回
        if (user == null || commentList.size() == 0)
            return ResponseResult.okResult(commentList);

        //获取当前用户点赞过的评论

        List<ApCommentVo> apCommentVos = new ArrayList<>();
        for (ApComment apComment : commentList) {
            ApCommentLike commentLike = mongoTemplate.findOne(Query.query(Criteria
                            .where("authorId").is(user.getId())
                            .and("commentId").is(apComment.getId()))
                    , ApCommentLike.class);

            ApCommentVo apCommentVo = new ApCommentVo();
            BeanUtils.copyProperties(apComment, apCommentVo);
            // 用户点过赞设置值为0(点赞)
            if (commentLike != null) {
                apCommentVo.setOperation((short) 0);
            }
            apCommentVo.setReply(apComment.getReply());
            apCommentVos.add(apCommentVo);

        }

        return ResponseResult.okResult(apCommentVos);
    }
}
